package com.lujianfei.mqtt.service

import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Binder
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import com.lujianfei.mqtt.Constant
import com.lujianfei.mqtt.R
import com.lujianfei.mqtt.callback.MqttServiceCallBack
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.*


class MQTTService : Service() {
    private var conOpt: MqttConnectOptions? = null
    companion object {
        private val TAG = MQTTService::class.java.simpleName
    }
    private var mMqttServiceCallback: MqttServiceCallBack? = null

    override fun onCreate() {
        super.onCreate()
        Log.e(TAG, "onCreate")
        init()
    }

    private fun init() { // 服务器地址（协议+地址+端口号）
        val uri = Constant.MQ.host
        client = MqttAndroidClient(this, uri, Constant.MQ.clientId)
        // 设置MQTT监听并且接受消息
        client?.setCallback(mqttCallback)
        conOpt = MqttConnectOptions()
        conOpt?.apply {
            // 清除缓存
            isCleanSession = true
            // 设置超时时间，单位：秒
            connectionTimeout = 10
            // 心跳包发送间隔，单位：秒
            keepAliveInterval = 20
            // 用户名
            userName = Constant.MQ.userName
            // 密码
            password = Constant.MQ.passWord.toCharArray() //将字符串转换为字符串数组
        }
        // last will message
        var doConnect = true
        val message = "{\"terminal_uid\":\"${Constant.MQ.clientId}\"}"
        Log.e(TAG, "message是:$message")
        val topic = Constant.MQ.subscribeTopic
        val qos = 0
        val retained = false
        try {
            conOpt?.setWill(topic, message.toByteArray(), qos, retained)
        } catch (e: Exception) {
            Log.i(TAG, "Exception Occured", e)
            doConnect = false
            iMqttActionListener.onFailure(null, e)
        }
        if (doConnect) {
            doClientConnection()
        }
    }

    override fun onDestroy() {
        stopSelf()
        try {
            client?.apply {
                disconnect()
                unregisterResources()
            }
        } catch (e: MqttException) {
            Log.e(TAG,"$e")
        }
        super.onDestroy()
    }

    /** 连接MQTT服务器  */
    private fun doClientConnection() {
        client?.let {client->
            if (!client.isConnected && isConnectIsNormal) {
                try {
                    client.connect(conOpt, null, iMqttActionListener)
                } catch (e: MqttException) {
                    Log.e(TAG,"$e")
                }
            }
        }
    }

    // MQTT是否连接成功
    private val iMqttActionListener: IMqttActionListener = object : IMqttActionListener {
        override fun onSuccess(arg0: IMqttToken) {
            Log.i(TAG, "连接成功 ")
            try { // 订阅myTopic话题
                client?.subscribe(Constant.MQ.subscribeTopic, 1)
            } catch (e: MqttException) {
                Log.e(TAG,"$e")
            }
        }

        override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
            Log.e(TAG,"$exception")
            // 连接失败，重连
        }
    }
    // MQTT监听并且接受消息
    private val mqttCallback: MqttCallback = object : MqttCallback {
        @Throws(Exception::class)
        override fun messageArrived(topic: String, message: MqttMessage) {
            val str1 = String(message.payload)
            mMqttServiceCallback?.onMessageReceive(str1)
            val str2 = topic + ";qos:" + message.qos + ";retained:" + message.isRetained
            Log.i(TAG, "messageArrived:$str1")
            Log.i(TAG, str2)
        }

        override fun deliveryComplete(token: IMqttDeliveryToken?) {
            Log.i(TAG,"$token")
        }
        override fun connectionLost(cause: Throwable?) {
            // 失去连接，重连
            Log.e(TAG,"$cause")
        }
    }

    /** 判断网络是否连接  */
    private val isConnectIsNormal: Boolean
        get() {
            val connectivityManager = this.applicationContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val info = connectivityManager.activeNetworkInfo
            return if (info != null && info.isAvailable) {
                val name = info.typeName
                Log.i(TAG, "MQTT 当前网络名称：$name")
                true
            } else {
                Log.i(TAG, "MQTT 没有可用网络")
                false
            }
        }

    override fun onBind(intent: Intent?): IBinder {
        Log.e(TAG, "onBind")
        return CustomBinder()
    }

    fun setOnCallback(mqttCallBack: MqttServiceCallBack) {
        this.mMqttServiceCallback = mqttCallBack
    }

    inner class CustomBinder : Binder() {
        val service: MQTTService
            get() = this@MQTTService
    }

    fun toCreateNotification(message: String?) {
        val pendingIntent = PendingIntent.getActivity(this, 1, Intent(this, MQTTService::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
        val builder = NotificationCompat.Builder(this) //3、创建一个通知，属性太多，使用构造器模式
        val notification: Notification = builder
                .setTicker("测试标题")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("")
                .setContentText(message)
                .setContentInfo("")
                .setContentIntent(pendingIntent) //点击后才触发的意图，“挂起的”意图
                .setAutoCancel(true) //设置点击之后notification消失
                .build()
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        startForeground(0, notification)
        notificationManager.notify(0, notification)
    }

    private var client: MqttAndroidClient? = null

    fun publish(msg: String) {
        val qos = 0
        val retained = false
        try {
            client?.publish(Constant.MQ.publishTopic, msg.toByteArray(), qos, retained)
        } catch (e: MqttException) {
            Log.e(TAG,"$e")
        }
    }
}